package com.hyz.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONUtil;
import com.hyz.entity.Comment;
import com.hyz.service.CommentsService;
import jodd.util.ArraysUtil;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import java.util.*;

import static com.hyz.utils.RedisConstants.*;

/**
 * @author HGD
 * @date 2023/2/19 16:13
 */
@Component
public class CronTask {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private CommentsService service;
    @Resource
    private Redisson redisson;

    @Scheduled(cron = "0/3 * * ? * ?")
    public void insAndDelTask() {
        // TODO：将两个批量操作分成两个线程来做
        new Thread(this::saveData).start();
        new Thread(this::deleteData).start();
    }

    /**
     * 将写缓存的数据保存到数据库中
     */
    public void saveData() {
        // 将写缓存的数据批量导入数据库中
        // 获取写缓存的操作锁
        RLock cacheLock = redisson.getLock(INSET_CACHE_KEY);
        while (true) {
            // 获取锁成功进入批量导入状态，获取锁失败则再次获取
            boolean isCacheLock = cacheLock.tryLock();
            try {
                // 获取锁成功
                if (isCacheLock) {
                    // 拿到当前的写缓存数据
                    Set<Object> keys = stringRedisTemplate.opsForHash().keys(INSERT_KEY);
                    List<Object> values = stringRedisTemplate.opsForHash().multiGet(INSERT_KEY, keys);
                    for (Object key : keys) {
                        stringRedisTemplate.opsForHash().delete(INSERT_KEY, key.toString());
                    }
                    // 批量保存到数据库中
                    service.saveBatch(BeanUtil.copyToList(values, Comment.class));
                    // 获取当前所有评论缓存的key，然后更新
                    Set<String> videoKeys = stringRedisTemplate.keys(VIDEO_ID_KEY);
                    if (videoKeys != null) {
                        for (String videoKey : videoKeys) {
                            List<Comment> list = service.lambdaQuery().eq(Comment::getVideoId, videoKey).list();
                            String commentJson = JSONUtil.toJsonStr(list);
                            stringRedisTemplate.opsForValue().set(VIDEO_ID_KEY + videoKey, commentJson);
                        }
                    }
                    break;
                }
            } finally {
                cacheLock.unlock();
            }
        }
    }

    /**
     * 将删除缓存保存到数据库中
     */
    public void deleteData() {
        Set<String> deleteIds = stringRedisTemplate.opsForSet().members(DELETE_KEY);
        if (deleteIds != null) {
            List<String> ids = new ArrayList<>(deleteIds);
            service.removeBatchByIds(ids);
        }
    }
}
